package com.inspire.ijc.agent.storage;

import com.inspire.ijc.agent.storage.entity.CallMethod;
import com.inspire.ijc.agent.storage.entity.CallThread;
import com.inspire.ijc.agent.utils.CallGraphUtil;
import com.inspire.ijc.agent.utils.QueueToStack;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Stack;

/**
 * @author ：inspire
 * @date ：Created in 2023/4/13 11:49
 * @description：
 * @modified By：inspire
 * @version:
 */
public class IStack {
    public static void push(int id,String className,String methodName){
//        System.out.println("push className:"+className+",methodName:"+methodName);

        long threadID=Thread.currentThread().getId();
        String threadName = Thread.currentThread().getName();

        boolean callThreadExist=false;

        for(CallThread callThread:AllContext.CALLTHREADLIST){
            if(callThread.getThreadId()==threadID){
                callThreadExist=true;
                callThread.setCurrentOrder(callThread.getCurrentOrder()+1);
                callThread.setCurrentDepth(callThread.getCurrentDepth()+1);
                callThread.setNearPushTime(System.nanoTime());//设置最新的push时间
                callThread.setMethodIdTimes(id);
                QueueToStack<CallMethod> stack = AllContext.THREADCALL.get(threadID);
                stack.push(new CallMethod(className,methodName,System.nanoTime(),callThread.getCurrentOrder(),callThread.getCurrentDepth(),id));

                break;
            }
        }
        if(!callThreadExist){
            CallMethod callMethod=new CallMethod(className,methodName,System.nanoTime(),1,id);
            QueueToStack<CallMethod> stack=new QueueToStack<CallMethod>();
            stack.push(callMethod);
            CallThread callThread = new CallThread(threadID, threadName, 1, 0, new Date());
            callThread.setNearPushTime(System.nanoTime());//设置最新的push时间
            callThread.setMethodIdTimes(id);
            AllContext.CALLTHREADLIST.add(callThread);
            AllContext.THREADCALL.put(threadID,stack);
        }
    }

    public static void pop(){
        long threadID=Thread.currentThread().getId();
        for(CallThread callThread:AllContext.CALLTHREADLIST){
            if(callThread.getThreadId()==threadID){
                QueueToStack<CallMethod> stack = AllContext.THREADCALL.get(threadID);
                CallMethod callMethod = stack.pop();
//                System.out.println("pop className:"+callMethod.getClassName()+",methodName:"+callMethod.getMethodName());
                long costTime=System.nanoTime()-callMethod.getStartTime();
                callMethod.setCostTime(CallGraphUtil.nanosToMillis(costTime));

                callThread.setCurrentDepth(callThread.getCurrentDepth()-1);

                if(AllContext.PRINTLIST.containsKey(threadID)){
                    List<CallMethod> printCallMethods = AllContext.PRINTLIST.get(threadID);
                    printCallMethods.add(callMethod);
                }else{
                    List<CallMethod> printCallMethods=new ArrayList<CallMethod>();
                    printCallMethods.add(callMethod);
                    AllContext.PRINTLIST.put(threadID,printCallMethods);
                }

                //pop到最后一个元素，输出当前线程的调用栈，并删除此线程集合
                if(stack.size()==0){
                    //删除该线程的集合
                    AllContext.THREADCALL.remove(threadID);
                    //输出调用栈
                    CallGraphUtil.callGraph(callThread,TypeConstants.normal);
                    //监控出现异常栈的线程
                    CallGraphUtil.printExceptionCallGraph();
                }
                break;
            }
        }

    }
}
